#include <stdio.h>
#include <stdlib.h>
#include "struktio.h"
#include "pamet.h"
#include "unikat.h"

inline Qpodminka *malopameti(Qpodminka *ptr){malopameti((void*)ptr);return ptr;}

template <class T>
unsigned long strom_pridej_rek(SIOstrom<T> *&t,unsigned long &ind,T *p,SIOstrom<T> *&otec,SIOstrom<T> *&koren,SIOstrom<T> *&kon){
  if(p!=t->u){
    unsigned long a;
    if(((long)p)>((long)(t->u))){
      if(t->p==NULL){
        SIOstrom<T> *u=t->p=new SIOstrom<T>;
        malopameti(u);
        u->l=NULL;
        u->p=NULL;
        u->dalsi=NULL;
        u->cerveny=1;
        u->u=p;
        u->ind=ind++;
        a=u->ind;
        kon->dalsi=u;
        kon=u;
      }else a=strom_pridej_rek(t->p,ind,p,t,koren,kon);
      if(t->cerveny&&t->p->cerveny){
        if(t==koren) t->cerveny=0;
        else{
          int pravy=(otec->p==t);
          SIOstrom<T> *bratr=pravy?otec->l:otec->p;
          if(bratr!=NULL&&bratr->cerveny){
            bratr->cerveny=0;
            t->cerveny=0;
            otec->cerveny=1;
          }else{
            SIOstrom<T> *s=t;
            if(pravy){
              otec->p=s->l;
              s->l=otec;
              otec=s;
              s->cerveny=0;
              s->l->cerveny=1;
            }else{
              otec->l=s->p->p;
              s->p->p=otec;
              otec=s->p;
              s->p=otec->l;
              otec->l=s;
              otec->cerveny=0;
              otec->p->cerveny=1;
            }
          }
        }
      }
      return a;
    }else{
      if(t->l==NULL){
        SIOstrom<T> *u=t->l=new SIOstrom<T>;
        malopameti(u);
        u->l=NULL;
        u->p=NULL;
        u->dalsi=NULL;
        u->cerveny=1;
        u->u=p;
        u->ind=ind++;
        a=u->ind;
        kon->dalsi=u;
        kon=u;
      }else a=strom_pridej_rek(t->l,ind,p,t,koren,kon);
      if(t->cerveny&&t->l->cerveny){
        if(t==koren) t->cerveny=0;
        else{
          int levy=(otec->l==t);
          SIOstrom<T> *bratr=levy?otec->p:otec->l;
          if(bratr!=NULL&&bratr->cerveny){
            bratr->cerveny=0;
            t->cerveny=0;
            otec->cerveny=1;
          }else{
            SIOstrom<T> *s=t;
            if(levy){
              otec->l=s->p;
              s->p=otec;
              otec=s;
              s->cerveny=0;
              s->p->cerveny=1;
            }else{
              otec->p=s->l->l;
              s->l->l=otec;
              otec=s->l;
              s->l=otec->p;
              otec->p=s;
              otec->cerveny=0;
              otec->l->cerveny=1;
            }
          }
        }
      }
      return a;
    }
  }else{
    return t->ind;
  }
}

template <class T>
int strom_pridej(SIOstrom<T> *&t,unsigned long &ind,T *p,SIOstrom<T> *&poc,SIOstrom<T> *&kon){ //1 pokud doslo k pridani
  SIOstrom<T> *u=t;
  if(t==NULL){
    u=t=new SIOstrom<T>;
    malopameti(u);
    t->l=NULL;
    t->p=NULL;
    t->dalsi=NULL;
    t->cerveny=0;
    t->u=p;
    t->ind=ind++;
    poc=kon=t;
    return 1;
  }else{
    unsigned long i=ind;
    strom_pridej_rek(t,ind,p,u,u,kon);
    return i==ind?0:1;
  }
}

template <class T>
void smaz_strom(SIOstrom<T> *t){
  if(t){
    smaz_strom(t->l);
    smaz_strom(t->p);
    delete t;
  }
}

template <class T>
SIOstrom<T> *vytvor_strom(SIOstrom<T> *&t,unsigned long l){
  SIOstrom<T> *p;
  switch(l){
    case 0:
      return NULL;
    case 1:
      p=t;
      t=t->dalsi;
      return p;
    default:
      l--;
      unsigned long d=l/2;
      p=vytvor_strom(t,d);
      t->l=p;
      p=t;
      t=t->dalsi;
      p->p=vytvor_strom(t,l-d);
      return p;
  }
}

template <class T>
unsigned long strom_obsah(SIOstrom<T> *t,T *p){
  if(t==NULL){
    fprintf(stderr,"CHYBA: Neznamy pointer pri zapisu struktury do souboru.\r\n");
    exit(-1);
    return 0;
  }else{
    if(p!=t->u)
      if(((long)p)>((long)(t->u))) return strom_obsah(t->p,p);
      else return strom_obsah(t->l,p);
    else return t->ind;
  }
}

template <class T>
T *strom_obsah(SIOstrom<T> *t,unsigned long ind){
  if(t==NULL){
    fprintf(stderr,"CHYBA: Neznamy odkaz pri cteni struktury ze souboru.\r\n");
    exit(-1);
    return NULL;
  }else{
    if(ind!=t->ind)
      if(ind>t->ind) return strom_obsah(t->p,ind);
      else return strom_obsah(t->l,ind);
    else return t->u;
  }
}

void projdi_strom(Qstrom *u,SIOdata *dt){
  if(!u) return;
  if(strom_pridej(dt->ts,dt->sind,u,dt->spoc,dt->skon)){
    strom_pridej(dt->tr,dt->rind,u->vjmeno(),dt->rpoc,dt->rkon);
    projdi_strom(u->vsyn(),dt);
    projdi_strom(u->vbratr(),dt);
    projdi_strom(u->vdesint(),dt);
  }
}

void projdi_hrany(Qhrana *u,SIOdata *dt){
  if(!u) return;
  if(strom_pridej(dt->th,dt->hind,u,dt->hpoc,dt->hkon)){
    projdi_strom(u->vstrom(),dt);
    projdi_hrany(u->vretez1(),dt);
    projdi_hrany(u->vretez2(),dt);
    projdi_hrany(u->vvetev1(),dt);
    projdi_hrany(u->vvetev2(),dt);
  }
}

void projdi_podm(Qpodminka *p,SIOdata *dt){
  if(p){
    if(p->typ()<=_Snegace){
      Qpodminka *p1,*p2;
      p->obsah(p1,p2);
      projdi_podm(p1,dt);
      projdi_podm(p2,dt);
    }else{
      Qstrom *u1,*u2;
      p->obsah(u1,u2);
      projdi_strom(u1,dt);
      projdi_strom(u2,dt);
    }
  }
}

void uloz_podm(SIOstrom<Qstrom> *t,Qpodminka *p,FILE *f){
  char typ=p==NULL?0:p->typ();
  fwrite(&typ,sizeof(typ),1,f);
  if(typ){
    if(typ<=_Snegace){
      Qpodminka *p1,*p2;
      p->obsah(p1,p2);
      uloz_podm(t,p1,f);
      if(typ<_Snegace) uloz_podm(t,p2,f);
    }else{
      Qstrom *u1,*u2;
      p->obsah(u1,u2);
      unsigned long i;
      i=strom_obsah(t,u1);
      fwrite(&i,sizeof(i),1,f);
      i=strom_obsah(t,u2);
      fwrite(&i,sizeof(i),1,f);
    }
  }
}

void Qprogram::uloz(FILE *f){
  SIOdata *dt=new SIOdata();
  malopameti(dt);
  strom_pridej(dt->th,dt->hind,(Qhrana*)NULL,dt->hpoc,dt->hkon);
  strom_pridej(dt->ts,dt->sind,(Qstrom*)NULL,dt->spoc,dt->skon);
  strom_pridej(dt->tr,dt->rind,(Retezec*)NULL,dt->rpoc,dt->rkon);
  Qfaze *fz;
  Qpravidlo *prav;
  fz=_faze;
  for(;fz!=NULL;fz=fz->dal()){
    prav=fz->pravidlo();
    for(;prav!=NULL;prav=prav->dal()){
      projdi_hrany(prav->levyretez(),dt);
      projdi_hrany(prav->pravyretez(),dt);
      projdi_podm(prav->podminka(),dt);
    }
  }
  unsigned long i;
  dt->rind--;
  fwrite(&dt->rind,sizeof(dt->rind),1,f);
  dt->rpoc=dt->rpoc->dalsi;
  while(dt->rpoc){
    i=1;
    char *ch=dt->rpoc->u->vobsah();
    while(*ch) {i++;ch++;}
    ch=dt->rpoc->u->vobsah();
    fwrite(ch,sizeof(char),i,f);
    dt->rpoc=dt->rpoc->dalsi;
  }
  dt->sind--;
  fwrite(&dt->sind,sizeof(dt->sind),1,f);
  dt->spoc=dt->spoc->dalsi;
  while(dt->spoc){
    i=strom_obsah(dt->tr,dt->spoc->u->vjmeno());fwrite(&i,sizeof(i),1,f);
    i=strom_obsah(dt->ts,dt->spoc->u->vsyn());fwrite(&i,sizeof(i),1,f);
    i=strom_obsah(dt->ts,dt->spoc->u->vbratr());fwrite(&i,sizeof(i),1,f);
    i=strom_obsah(dt->ts,dt->spoc->u->vdesint());fwrite(&i,sizeof(i),1,f);
    int k=dt->spoc->u->vkonst();
    fwrite(&k,sizeof(k),1,f);
    dt->spoc=dt->spoc->dalsi;
  }
  dt->hind--;
  fwrite(&dt->hind,sizeof(dt->hind),1,f);
  dt->hpoc=dt->hpoc->dalsi;
  while(dt->hpoc){
    i=strom_obsah(dt->ts,dt->hpoc->u->vstrom());fwrite(&i,sizeof(i),1,f);
    i=strom_obsah(dt->th,dt->hpoc->u->vretez1());fwrite(&i,sizeof(i),1,f);
    i=strom_obsah(dt->th,dt->hpoc->u->vretez2());fwrite(&i,sizeof(i),1,f);
    i=strom_obsah(dt->th,dt->hpoc->u->vvetev1());fwrite(&i,sizeof(i),1,f);
    i=strom_obsah(dt->th,dt->hpoc->u->vvetev2());fwrite(&i,sizeof(i),1,f);
    dt->hpoc=dt->hpoc->dalsi;
  }
  fz=_faze;
  i=0;
  while(fz){i++; fz=fz->dal();}
  fwrite(&i,sizeof(i),1,f);
  fz=_faze;
  for(;fz;fz=fz->dal()){
    prav=fz->pravidlo();
    i=0;
    while(prav){i++;prav=prav->dal();}
    fwrite(&i,sizeof(i),1,f);
    prav=fz->pravidlo();
    for(;prav;prav=prav->dal()){
      i=strom_obsah(dt->th,prav->levyretez());
      fwrite(&i,sizeof(i),1,f);
      i=strom_obsah(dt->th,prav->pravyretez());
      fwrite(&i,sizeof(i),1,f);
      uloz_podm(dt->ts,prav->podminka(),f);
    }
  }
  smaz_strom(dt->tr);
  smaz_strom(dt->ts);
  smaz_strom(dt->th);
  delete dt;
}

Qpodminka *nacti_podm(SIOstrom<Qstrom> *t,FILE *f){
  char typ;
  fread(&typ,sizeof(typ),1,f);
  Qpodminka *p1,*p2;
  Qstrom *u1,*u2;
  unsigned long i1,i2;
  switch(typ){
    case _Sdisjunkce:
      p1=nacti_podm(t,f);
      p2=nacti_podm(t,f);
      return malopameti(new Qdisjunkce(p1,p2));
    case _Skonjunkce:
      p1=nacti_podm(t,f);
      p2=nacti_podm(t,f);
      return malopameti(new Qkonjunkce(p1,p2));
    case _Snegace:
      return malopameti(new Qnegace(nacti_podm(t,f)));
    case _Srovnost:
      fread(&i1,sizeof(i1),1,f);u1=strom_obsah(t,i1);if(u1) u1->pocplus();
      fread(&i2,sizeof(i2),1,f);u2=strom_obsah(t,i2);if(u2) u2->pocplus();
      return malopameti(new Qrovnost(u1,u2));
    case _Snerovnost:
      fread(&i1,sizeof(i1),1,f);u1=strom_obsah(t,i1);if(u1) u1->pocplus();
      fread(&i2,sizeof(i2),1,f);u2=strom_obsah(t,i2);if(u2) u2->pocplus();
      return malopameti(new Qnerovnost(u1,u2));
    case _Sdans:
      fread(&i1,sizeof(i1),1,f);u1=strom_obsah(t,i1);if(u1) u1->pocplus();
      fread(&i2,sizeof(i2),1,f);u2=strom_obsah(t,i2);if(u2) u2->pocplus();
      return malopameti(new Qdans(u1,u2));
    case _Shors:
      fread(&i1,sizeof(i1),1,f);u1=strom_obsah(t,i1);if(u1) u1->pocplus();
      fread(&i2,sizeof(i2),1,f);u2=strom_obsah(t,i2);if(u2) u2->pocplus();
      return malopameti(new Qhors(u1,u2));
    default: return NULL;
  }
}

Qfaze *cti_program(FILE *f){
  SIOstrom<Qhrana> *th=NULL,*ph;
  SIOstrom<Qstrom> *ts=NULL,*ps;
  SIOstrom<Retezec> *tr=NULL,*pr,*qr;
  unsigned long ind,i,j;
  fread(&ind,sizeof(ind),1,f);
  for(i=ind;i>=1;){
    pr=new SIOstrom<Retezec>;
    malopameti(pr);
    pr->l=NULL;
    pr->p=NULL;
    pr->dalsi=tr;
    pr->u=NULL;
    pr->ind=i--;
    tr=pr;
  }
  pr=new SIOstrom<Retezec>;
  malopameti(pr);
  pr->l=NULL;
  pr->p=NULL;
  pr->dalsi=tr;
  pr->u=NULL;
  pr->ind=0;
  qr=tr=pr;
  ind++;
  tr=vytvor_strom(tr,ind);
  pr=pr->dalsi;
  while(pr!=NULL){
    unsigned long l=1;
    char ch;
    fread(&ch,sizeof(char),1,f);
    while(ch) {l++;fread(&ch,sizeof(char),1,f);}
    fseek(f,-l,SEEK_CUR);
    char *s=new char[l];
    malopameti(s);
    fread(s,sizeof(char),l,f);
    pr->u=new Retezec(s);
    malopameti(pr->u); delete[] s;
    pr->u->npoc(0);
    pr=pr->dalsi;
  }
  fread(&ind,sizeof(ind),1,f);
  for(i=ind;i>=1;){
    ps=new SIOstrom<Qstrom>;
    malopameti(ps);
    ps->l=NULL;
    ps->p=NULL;
    ps->dalsi=ts;
    ps->u=new Qstrom((Retezec*)NULL,0);
    malopameti(ps->u);
    ps->u->npoc(0);
    ps->ind=i--;
    ts=ps;
  }
  ps=new SIOstrom<Qstrom>;
  malopameti(ps);
  ps->l=NULL;
  ps->p=NULL;
  ps->dalsi=ts;
  ps->u=NULL;
  ps->ind=0;
  ts=ps;
  ind++;
  ts=vytvor_strom(ts,ind);
  ps=ps->dalsi;
  while(ps!=NULL){
    fread(&i,sizeof(i),1,f);Retezec *jm=kretezec(strom_obsah(tr,i)->vobsah());ps->u->njmeno(jm);
    fread(&i,sizeof(i),1,f);ps->u->nsyn(strom_obsah(ts,i));ps->u->adsyn();
    fread(&i,sizeof(i),1,f);ps->u->nbratr(strom_obsah(ts,i));ps->u->adbratr();
    fread(&i,sizeof(i),1,f);ps->u->ndesint(strom_obsah(ts,i));ps->u->addesint();
    int k;
    fread(&k,sizeof(k),1,f);ps->u->nkonst(k);
    ps=ps->dalsi;
  }
  fread(&ind,sizeof(ind),1,f);
  for(i=ind;i>=1;){
    ph=new SIOstrom<Qhrana>;
    malopameti(ph);
    ph->l=NULL;
    ph->p=NULL;
    ph->dalsi=th;
    ph->u=new Qhrana(NULL);
    malopameti(ph->u);
    ph->u->npoc(0);
    ph->ind=i--;
    th=ph;
  }
  ph=new SIOstrom<Qhrana>;
  malopameti(ph);
  ph->l=NULL;
  ph->p=NULL;
  ph->dalsi=th;
  ph->u=NULL;
  ph->ind=0;
  th=ph;
  ind++;
  th=vytvor_strom(th,ind);
  ph=ph->dalsi;
  while(ph!=NULL){
    fread(&i,sizeof(i),1,f);ph->u->nstrom(strom_obsah(ts,i));ph->u->adstrom();
    fread(&i,sizeof(i),1,f);ph->u->nretez1(strom_obsah(th,i));ph->u->adretez1();
    fread(&i,sizeof(i),1,f);ph->u->nretez2(strom_obsah(th,i));
    fread(&i,sizeof(i),1,f);ph->u->nvetev1(strom_obsah(th,i));ph->u->advetev1();
    fread(&i,sizeof(i),1,f);ph->u->nvetev2(strom_obsah(th,i));
    ph=ph->dalsi;
  }
  fread(&i,sizeof(i),1,f);
  Qfaze *fz=NULL,*f1,*f2;
  while(i){
    fread(&j,sizeof(j),1,f);
    Qpravidlo *prav=NULL,*p1,*p2;
    while(j){
      unsigned long i1,i2;
      fread(&i1,sizeof(i1),1,f);
      fread(&i2,sizeof(i2),1,f);
      Qpodminka *podm=nacti_podm(ts,f);
      if(podm==NULL) p2=new Qpravidlo(strom_obsah(th,i1),strom_obsah(th,i2));
      else p2=new Qpravidlo(strom_obsah(th,i1),strom_obsah(th,i2),podm);
      malopameti(p2);
      p2->levyretez()->pocplus();
      p2->pravyretez()->pocplus();
      if(prav==NULL) {prav=p2;p1=p2;}
      else {p1->nastav(p2);p1=p2;}
      j--;
    }
    f2=new Qfaze(prav);
    malopameti(f2);
    if(fz==NULL) {fz=f2;f1=f2;}
    else {f1->nastav(f2);f1=f2;}
    i--;
  }
  smaz_strom(th);
  smaz_strom(ts);
  while(qr){
    delete qr->u;
    SIOstrom<Retezec> *p=qr;
    qr=qr->dalsi;
    delete p;
  }
  return fz;
}

void Qprogram::nacti(FILE *f){
  Qfaze *fz=cti_program(f),*p;
  if(!fz) return;
  if(_faze){
    p=fz;
    while(p->dal()) p=p->dal();
    p->nastav(_faze);
    _faze=fz;
  }else _faze=fz;
  ocislovat();
}

Qprogram::Qprogram(FILE *f){
  _faze=cti_program(f);
  ocislovat();
}

void Qvstup::uloz(FILE *f){
  SIOdata *dt=new SIOdata();
  malopameti(dt);
  strom_pridej(dt->th,dt->hind,(Qhrana*)NULL,dt->hpoc,dt->hkon);
  strom_pridej(dt->ts,dt->sind,(Qstrom*)NULL,dt->spoc,dt->skon);
  strom_pridej(dt->tr,dt->rind,(Retezec*)NULL,dt->rpoc,dt->rkon);
  Qvstup *p=this;
  while(p){
    projdi_hrany(p->vhrana(),dt);
    p=p->dalsi();
  }
  unsigned long i;
  dt->rind--;
  fwrite(&dt->rind,sizeof(dt->rind),1,f);
  dt->rpoc=dt->rpoc->dalsi;
  while(dt->rpoc){
    i=1;
    char *ch=dt->rpoc->u->vobsah();
    while(*ch) {i++;ch++;}
    ch=dt->rpoc->u->vobsah();
    fwrite(ch,sizeof(char),i,f);
    dt->rpoc=dt->rpoc->dalsi;
  }
  dt->sind--;
  fwrite(&dt->sind,sizeof(dt->sind),1,f);
  dt->spoc=dt->spoc->dalsi;
  while(dt->spoc){
    i=strom_obsah(dt->tr,dt->spoc->u->vjmeno());fwrite(&i,sizeof(i),1,f);
    i=strom_obsah(dt->ts,dt->spoc->u->vsyn());fwrite(&i,sizeof(i),1,f);
    i=strom_obsah(dt->ts,dt->spoc->u->vbratr());fwrite(&i,sizeof(i),1,f);
    i=strom_obsah(dt->ts,dt->spoc->u->vdesint());fwrite(&i,sizeof(i),1,f);
    int k=dt->spoc->u->vkonst();
    fwrite(&k,sizeof(k),1,f);
    dt->spoc=dt->spoc->dalsi;
  }
  dt->hind--;
  fwrite(&dt->hind,sizeof(dt->hind),1,f);
  dt->hpoc=dt->hpoc->dalsi;
  while(dt->hpoc){
    i=strom_obsah(dt->ts,dt->hpoc->u->vstrom());fwrite(&i,sizeof(i),1,f);
    i=strom_obsah(dt->th,dt->hpoc->u->vretez1());fwrite(&i,sizeof(i),1,f);
    i=strom_obsah(dt->th,dt->hpoc->u->vretez2());fwrite(&i,sizeof(i),1,f);
    i=strom_obsah(dt->th,dt->hpoc->u->vvetev1());fwrite(&i,sizeof(i),1,f);
    i=strom_obsah(dt->th,dt->hpoc->u->vvetev2());fwrite(&i,sizeof(i),1,f);
    dt->hpoc=dt->hpoc->dalsi;
  }
  i=0;
  p=this;
  while(p) {i++;p=p->dalsi();}
  fwrite(&i,sizeof(i),1,f);
  p=this;
  while(p){
    i=(p->unik!=NULL); fwrite(&i,sizeof(i),1,f);
    i=strom_obsah(dt->th,p->vhrana());fwrite(&i,sizeof(i),1,f);
    p=p->dalsi();
  }
  smaz_strom(dt->tr);
  smaz_strom(dt->ts);
  smaz_strom(dt->th);
  delete dt;
}

void zhrek(Ustrom *u,Qhrana *h){
  Qstrom *s=h->vstrom();
  u->unikat(s);
  h->nstrom(s);
  if(h->vvetev1()) zhrek(u,h->vvetev1());
  if(h->vretez1()) zhrek(u,h->vretez1());
}

void zarad_hrany(Ustrom *u,Qhrana *h){
  while(h->vretez2()) h=h->vretez2();
  zhrek(u,h);
}

Qvstup *nacti_graf(FILE *f){
  SIOstrom<Qhrana> *th=NULL,*ph;
  SIOstrom<Qstrom> *ts=NULL,*ps;
  SIOstrom<Retezec> *tr=NULL,*pr,*qr;
  unsigned long ind,i,j;
  fread(&ind,sizeof(ind),1,f);
  for(i=ind;i>=1;){
    pr=new SIOstrom<Retezec>;
    malopameti(pr);
    pr->l=NULL;
    pr->p=NULL;
    pr->dalsi=tr;
    pr->u=NULL;
    pr->ind=i--;
    tr=pr;
  }
  pr=new SIOstrom<Retezec>;
  malopameti(pr);
  pr->l=NULL;
  pr->p=NULL;
  pr->dalsi=tr;
  pr->u=NULL;
  pr->ind=0;
  qr=tr=pr;
  ind++;
  tr=vytvor_strom(tr,ind);
  pr=pr->dalsi;
  while(pr!=NULL){
    unsigned long l=1;
    char ch;
    fread(&ch,sizeof(char),1,f);
    while(ch) {l++;fread(&ch,sizeof(char),1,f);}
    fseek(f,-l,SEEK_CUR);
    char *s=new char[l];
    malopameti(s);
    fread(s,sizeof(char),l,f);
    pr->u=new Retezec(s);
    malopameti(pr->u); delete[] s;
    pr->u->npoc(0);
    pr=pr->dalsi;
  }
  fread(&ind,sizeof(ind),1,f);
  for(i=ind;i>=1;){
    ps=new SIOstrom<Qstrom>;
    malopameti(ps);
    ps->l=NULL;
    ps->p=NULL;
    ps->dalsi=ts;
    ps->u=new Qstrom((Retezec*)NULL,0);
    malopameti(ps->u);
    ps->u->npoc(0);
    ps->ind=i--;
    ts=ps;
  }
  ps=new SIOstrom<Qstrom>;
  malopameti(ps);
  ps->l=NULL;
  ps->p=NULL;
  ps->dalsi=ts;
  ps->u=NULL;
  ps->ind=0;
  ts=ps;
  ind++;
  ts=vytvor_strom(ts,ind);
  ps=ps->dalsi;
  while(ps!=NULL){
    fread(&i,sizeof(i),1,f);Retezec *jm=kretezec(strom_obsah(tr,i)->vobsah());ps->u->njmeno(jm);
    fread(&i,sizeof(i),1,f);ps->u->nsyn(strom_obsah(ts,i));ps->u->adsyn();
    fread(&i,sizeof(i),1,f);ps->u->nbratr(strom_obsah(ts,i));ps->u->adbratr();
    fread(&i,sizeof(i),1,f);ps->u->ndesint(strom_obsah(ts,i));ps->u->addesint();
    int k;
    fread(&k,sizeof(k),1,f);ps->u->nkonst(k);
    ps=ps->dalsi;
  }
  fread(&ind,sizeof(ind),1,f);
  for(i=ind;i>=1;){
    ph=new SIOstrom<Qhrana>;
    malopameti(ph);
    ph->l=NULL;
    ph->p=NULL;
    ph->dalsi=th;
    ph->u=new Qhrana(NULL);
    malopameti(ph->u);
    ph->u->npoc(0);
    ph->ind=i--;
    th=ph;
  }
  ph=new SIOstrom<Qhrana>;
  malopameti(ph);
  ph->l=NULL;
  ph->p=NULL;
  ph->dalsi=th;
  ph->u=NULL;
  ph->ind=0;
  th=ph;
  ind++;
  th=vytvor_strom(th,ind);
  ph=ph->dalsi;
  while(ph!=NULL){
    fread(&i,sizeof(i),1,f);ph->u->nstrom(strom_obsah(ts,i));ph->u->adstrom();
    fread(&i,sizeof(i),1,f);ph->u->nretez1(strom_obsah(th,i));
    fread(&i,sizeof(i),1,f);ph->u->nretez2(strom_obsah(th,i));
    fread(&i,sizeof(i),1,f);ph->u->nvetev1(strom_obsah(th,i));ph->u->advetev1();
    fread(&i,sizeof(i),1,f);ph->u->nvetev2(strom_obsah(th,i));
    if(!ph->u->vvetev2())ph->u->adretez1();

    ph=ph->dalsi;
  }
  fread(&ind,sizeof(ind),1,f);
  Qvstup *v=NULL,*k;
  while(ind){
    fread(&j,sizeof(j),1,f);
    fread(&i,sizeof(i),1,f);
    Qvstup *p=new Qvstup(strom_obsah(th,i),NULL,j);
    malopameti(p);
    if(p->vhrana()){
      p->vhrana()->pocplus();
      if(j) zarad_hrany(p->vunik(),p->vhrana());
    }
    if(v){
      k->ndalsi(p);
      k=p;
    }else v=k=p;
    ind--;
  }
  smaz_strom(th);
  smaz_strom(ts);
  while(qr){
    delete qr->u;
    SIOstrom<Retezec> *p=qr;
    qr=qr->dalsi;
    delete p;
  }
  return v;
}

void Qvstup::nacti(FILE *f){
  Qvstup *p=nacti_graf(f),*q,*d;
  Qhrana *h;
  Ustrom *u;
  if(!p) return;
  q=p;while(q->dalsi()) q=q->dalsi();
  h=p->vhrana();p->nhrana(hrana);hrana=h;
  d=p->dalsi();p->ndalsi(dal);dal=d;
  u=p->vunik();p->nunik(unik);unik=u;
  q->ndalsi(p);
}

Qvstup::Qvstup(FILE *f,int un){
  if(un) {unik=new Ustrom; malopameti(unik);}
  Qvstup *p=nacti_graf(f);
  hrana=p->vhrana();
  dal=p->dalsi();
  unik=p->vunik();
  p->nhrana(NULL);
  p->ndalsi(NULL);
  p->nunik(NULL);
  delete p;
}